using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data.Objects.DataClasses;
using System.Linq;
using FPP.Controllers;
using FPP.Utilities;

namespace FPP.Models
{
    public partial class FamousPerson : EntityObject, IValidate
    {
        #region Primitive Properties

        public virtual int Id
        {
            get;
            set;
        }

        public virtual string DisplayName
        {
            get;
            set;
        }

        [Display(Name = "Date of Birth")]
        [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:d}")]
        public virtual DateTime DateOfBirth
        {
            get;
            set;
        }

        [Display(Name = "Date of Death")]
        [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:d}")]
        public virtual DateTime? DateOfDeath
        {
            get;
            set;
        }

        [Required(ErrorMessage = "WikiLink is required")]
        [RegularExpression(".*wikipedia.*", ErrorMessage = "URL must be from wikipedia")]
        public virtual string WikiLink
        {
            get;
            set;
        }

        public virtual int? AddedBy
        {
            get;
            set;
        }

        private int? _age;
        public virtual int? Age
        {
            get
            {
                if (_age == null) return 0;
                return _age;
            }
            set { _age = value; }
        }


        #endregion

        #region Validation

        public static ValidationResult ValidateBirthDate(DateTime birthDateToValidate)
        {
            if (birthDateToValidate.Date > DateTime.Now.AddDays(1))
            {
                return new ValidationResult("Date of Birth cannot be before today.");
            }

            return ValidationResult.Success;
        }

        #endregion

        #region Custom Values

        public void UpdateAge(bool forceSave = false)
        {
            if (Id == 0)
                return;

            DateTime now = (DateOfDeath == null) ? DateTime.Today : (DateTime)DateOfDeath;
            int age = now.Year - DateOfBirth.Year;
            if (DateOfBirth > now.AddYears(-age)) age--;
            Age = age;

            //Leave now if not requesting a force save
            if (!forceSave) return;
            using (var context = new fppEntities(DataAccess.ffpCString))
            {
                context.Connection.Open();
                var fp = context.FamousPersons.FirstOrDefault(f => f.Id == Id);
                if (fp != null)
                {
                    fp.Age = age;
                    context.ForceSave(fp);
                }
            }


        }

        public int DeathValue()
        {
            int rtn = 0;

            if (!(DateOfDeath == null))
            {
                rtn = new DateTime(DateOfDeath.Value.Subtract(DateOfBirth).Ticks).Year - 1;
                rtn = 100 - rtn;
                if (rtn < 0) rtn = rtn * -1;
            }

            return rtn;
        }

        #endregion

        #region Navigation Properties

        public WikiLink WikiData()
        {
            var newWikiData = new WikiLink();

            using (var context = new fppEntities(DataAccess.ffpCString))
            {
                context.Connection.Open();
                var save = false;

                var wList = context.WikiLinks.Where(l => l.Link == WikiLink).ToList();
                foreach (var wData in wList)
                {
                    newWikiData = wData;
                }

                //Need to add wiki link validation
                if (wList.Count == 0 && !string.IsNullOrEmpty(WikiLink))
                {
                    newWikiData.Link = WikiLink;
                    context.WikiLinks.AddObject(newWikiData);
                    save = true;
                }

                if (save) context.SaveChanges();
            }
            return newWikiData;
        }

        #endregion

        #region Communitive Properties

        public static List<FamousPerson> FamousPersons
        {
            get
            {
                using (var context = new fppEntities(DataAccess.ffpCString))
                {
                    _famousPersons = context.FamousPersons.ToList();
                }
                return _famousPersons;
            }
            set
            {
                _famousPersons = value;
            }
        }
        private static List<FamousPerson> _famousPersons;



        #endregion


        public bool Validate(ChangeAction action)
        {
            switch (action)
            {
                case ChangeAction.Insert:
                    if (FamousPersons.Any(fp => fp.WikiLink == WikiLink))
                    {
                        return false;
                    }
                    break;
            }

            return true;
        }
    }
}